"""
Common API tools for InCloud MCP Server
"""
import logging
import re
from typing import Dict, List, Any
from pydantic import Field

from ..static import load_prompt_understanding
from ..swagger.client import SwaggerClient
from ..swagger.tool_generator import APIExecutor
from ..config import get_config

logger = logging.getLogger(__name__)

tools = []
_CUSTOM_SERVICE_LIST = None


def set_custom_service_list(service_list):
    """Set custom service list for prompt understanding"""
    global _CUSTOM_SERVICE_LIST
    _CUSTOM_SERVICE_LIST = service_list


@tools.append
def PromptUnderstanding() -> str:
    """
    Always use this tool first to understand the user's query and convert it into suggestions from InCloud experts.
    """
    global _CUSTOM_SERVICE_LIST

    try:
        config = get_config()
        language = getattr(config, 'language', 'en')
    except:
        language = 'en'

    content = load_prompt_understanding(language)

    if _CUSTOM_SERVICE_LIST:
        # 支持中英文的服务列表替换
        if language == 'cn':
            pattern = r'支持的服务\s*：\s*\n(?:\s{3}- .+?\n)+'
            replacement = f"支持的服务：\n   - " + "\n   - ".join([f"{k}: {v}" for k, v in _CUSTOM_SERVICE_LIST])
        else:
            pattern = r'Supported Services\s*:\s*\n(?:\s{3}- .+?\n)+'
            replacement = f"Supported Services:\n   - " + "\n   - ".join([f"{k}: {v}" for k, v in _CUSTOM_SERVICE_LIST])

        content = re.sub(pattern, replacement, content, flags=re.DOTALL)

    return content


@tools.append
def TerminologyHelper(
    query: str = Field(description='用户查询或包含专业术语的文本')
) -> str:
    """
    专业术语助手：解释InCloud平台的专业术语，帮助理解主机、虚拟机、存储等概念的区别。
    """
    try:
        from ..terminology import terminology_processor, SERVICE_MAPPING

        # 标准化查询
        normalized_query = terminology_processor.normalize_query(query)

        # 获取服务建议
        service_suggestions = terminology_processor.suggest_correct_service(query)

        result = f"## 🏷️ InCloud 专业术语助手\n\n"
        result += f"**原始查询**: {query}\n\n"

        if normalized_query != query:
            result += f"**标准化查询**: {normalized_query}\n\n"

        result += "### 📚 术语说明\n\n"
        result += "**重要概念区别**：\n"
        result += "- **主机/云主机/虚拟主机** = `vhosts` (使用 icompute 服务)\n"
        result += "- **虚拟机** = `vm/vms` (使用 icompute 服务，与主机不同)\n"
        result += "- **存储卷/虚拟存储卷** = `virtualVolume` (使用 istorage 服务)\n"
        result += "- **网络** = `network` (使用 inetwork 服务)\n"
        result += "- **子网** = `subnet` (使用 inetwork 服务)\n\n"

        if service_suggestions:
            result += "### 🎯 推荐服务\n\n"
            for service, reason in service_suggestions:
                service_info = SERVICE_MAPPING.get(service, {})
                result += f"**{service}** ({service_info.get('name', service)})\n"
                result += f"- {reason}\n"
                if 'resources' in service_info:
                    result += f"- 管理资源: {', '.join(service_info['resources'].values())}\n"
                result += "\n"

        result += "### 💡 使用建议\n\n"
        result += "1. 明确区分**主机**(vhosts)和**虚拟机**(vm)的概念\n"
        result += "2. 根据资源类型选择正确的服务 (icompute/istorage/inetwork)\n"
        result += "3. 使用标准化的术语进行API调用\n"

        logger.info(f"Generated terminology help for query: {query}")
        return result

    except Exception as e:
        logger.error(f"Failed to generate terminology help: {e}")
        return f"术语助手错误: {str(e)}"


@tools.append
def ResourceOperationBlocker() -> str:
    """
    资源操作阻止器：说明为什么删除和修改操作被禁止，以及如何进行安全的资源管理。
    当用户尝试删除、修改或更新资源时，使用此工具提供替代方案。
    """
    try:
        result = """
## 🚫 高风险资源操作已被禁止

为了防止误操作导致资源损坏或服务中断，本系统已完全禁用以下操作：

### 📋 被禁止的操作类型

#### ❌ 删除操作 (DELETE)
- 删除虚拟主机 (DELETE /v1/vhosts/{id})
- 删除虚拟机 (DELETE /v1/vms/{id})
- 删除存储卷 (DELETE /v1/virtualVolume/{id})
- 删除网络资源 (DELETE /v1/networks/{id})
- 所有其他 DELETE 方法调用

#### ❌ 修改操作 (PUT)
- 修改虚拟主机配置 (PUT /v1/vhosts/{id})
- 修改虚拟机设置 (PUT /v1/vms/{id})
- 修改存储卷属性 (PUT /v1/virtualVolume/{id})
- 修改网络配置 (PUT /v1/networks/{id})
- 所有其他 PUT 方法调用

#### ❌ 更新操作 (PATCH)
- 更新资源属性 (PATCH /v1/resources/{id})
- 部分修改配置 (PATCH /v1/configs/{id})
- 所有其他 PATCH 方法调用

### 🛡️ 安全策略说明
1. **完全禁止**：DELETE、PUT、PATCH 方法都被配置为 "forbidden" 级别
2. **无例外**：即使使用 force_execute=True 也无法执行这些操作
3. **防误操作**：避免因误操作或AI误判导致的资源损坏或服务中断

### 💡 安全的替代方案

#### ✅ 允许的操作类型

##### 1. 查询操作 (GET)
- 查看资源列表：`GET /v1/vhosts`
- 查看资源详情：`GET /v1/vhosts/{id}`
- 查看资源状态：`GET /v1/vhosts/{id}/status`

##### 2. 创建操作 (POST)
- 创建新资源：`POST /v1/vhosts`
- 控制操作：`POST /v1/vms/{id}/start`
- 管理操作：`POST /v1/vms/{id}/stop`
- 重启操作：`POST /v1/vms/{id}/restart`

#### 🔄 资源管理建议

##### 替代删除操作：
1. **停止资源**：`POST /v1/resources/{id}/stop`
2. **禁用资源**：通过创建新配置替代旧配置
3. **标记资源**：使用标签系统标记不再使用的资源
4. **联系管理员**：请求管理员手动删除

##### 替代修改操作：
1. **创建新配置**：`POST /v1/configs` (创建新配置替代旧配置)
2. **版本管理**：创建新版本而不是修改现有版本
3. **配置模板**：使用配置模板创建标准化配置
4. **联系管理员**：请求管理员进行配置修改

### 🔧 当前安全配置

```yaml
method_policies:
  DELETE:
    default_level: "forbidden"  # 完全禁止删除
  PUT:
    default_level: "forbidden"  # 完全禁止修改
  PATCH:
    default_level: "forbidden"  # 完全禁止更新
  GET:
    default_level: "safe"       # 允许查询
  POST:
    default_level: "moderate"   # 允许创建和控制操作
```

### ⚠️ 重要提醒
- 此限制是为了保护您的重要资源和服务稳定性
- 删除和修改操作通常是不可逆的或有风险的
- 建议优先使用查询、创建和控制操作
- 如确需修改或删除，请联系系统管理员

### 📞 联系管理员
如果您确实需要执行被禁止的操作，请：
1. 联系系统管理员
2. 说明操作的必要性和预期效果
3. 管理员将通过安全的方式执行操作
"""

        logger.info("Generated resource operation blocker information")
        return result

    except Exception as e:
        logger.error(f"Failed to generate resource operation blocker info: {e}")
        return f"资源操作阻止器错误: {str(e)}"


@tools.append
def TerminologyConfigManager(
    action: str = Field(description='操作类型：reload(重新加载配置), show(显示当前配置), explain(解释术语)')
) -> str:
    """
    术语配置管理器：管理和查看专业术语配置。
    支持重新加载配置、显示当前配置、解释特定术语等操作。
    """
    try:
        from ..terminology import reload_terminology_config, get_terminology_reminder, get_concept_distinctions, _terminology_config

        if action.lower() == 'reload':
            reload_terminology_config()
            return """
## 🔄 术语配置已重新加载

术语配置文件 `terminology.yaml` 已重新加载，所有术语映射和规则已更新。

### 📋 配置来源
- 配置文件：`terminology.yaml`
- 包含：术语映射、服务映射、标准化规则、概念区别说明

### ✅ 重新加载完成
- 术语映射表已更新
- 服务映射已更新
- 标准化规则已更新
- 提示词模板已更新

现在所有术语相关功能都将使用最新的配置。
"""

        elif action.lower() == 'show':
            config_summary = f"""
## 📋 当前术语配置概览

### 🏷️ 术语映射统计
- 配置的术语数量：{len(_terminology_config.get('terminology_mapping', {}))}
- 服务映射数量：{len(_terminology_config.get('service_mapping', {}))}
- 标准化规则数量：{len(_terminology_config.get('normalization_rules', []))}

### 📚 主要术语类别
"""

            terminology_mapping = _terminology_config.get('terminology_mapping', {})
            service_groups = {}

            for term, config in terminology_mapping.items():
                service = config.get('service', 'unknown')
                if service not in service_groups:
                    service_groups[service] = []
                service_groups[service].append(term)

            for service, terms in service_groups.items():
                config_summary += f"\n#### {service.upper()} 服务\n"
                for term in terms[:5]:  # 只显示前5个
                    api_term = terminology_mapping[term].get('api_term', '')
                    config_summary += f"- **{term}** → `{api_term}`\n"
                if len(terms) > 5:
                    config_summary += f"- ... 还有 {len(terms) - 5} 个术语\n"

            # 显示概念区别
            distinctions = get_concept_distinctions()
            if distinctions:
                config_summary += "\n### 🔍 重要概念区别\n"
                for key, distinction in distinctions.items():
                    config_summary += f"\n#### {distinction.get('title', key)}\n"
                    config_summary += f"{distinction.get('description', '')}\n"

            return config_summary

        elif action.lower() == 'explain':
            terminology_reminder = get_terminology_reminder('cn')
            return f"""
## 📖 术语解释和使用指南

{terminology_reminder}

### 💡 使用建议
1. **查询操作**：使用标准术语进行查询
2. **API 调用**：使用正确的 API 术语
3. **服务选择**：根据资源类型选择正确的服务
4. **避免混淆**：特别注意主机(vhosts)和虚拟机(vm)的区别

### 🔧 配置管理
- 使用 `TerminologyConfigManager(action="reload")` 重新加载配置
- 使用 `TerminologyConfigManager(action="show")` 查看配置概览
- 术语配置文件：`terminology.yaml`
"""

        else:
            return f"""
## ❓ 术语配置管理器使用说明

### 支持的操作：

1. **reload** - 重新加载术语配置
   ```
   TerminologyConfigManager(action="reload")
   ```

2. **show** - 显示当前配置概览
   ```
   TerminologyConfigManager(action="show")
   ```

3. **explain** - 显示术语解释和使用指南
   ```
   TerminologyConfigManager(action="explain")
   ```

### 当前操作：{action}
请使用上述支持的操作之一。
"""

    except Exception as e:
        logger.error(f"Failed to manage terminology config: {e}")
        return f"术语配置管理器错误: {str(e)}"


@tools.append
def SecurityChecker(
    service: str = Field(description='InCloud service name'),
    method: str = Field(description='HTTP method'),
    path: str = Field(description='API path'),
    operation_id: str = Field(default="", description='Operation ID (optional)')
) -> Dict[str, Any]:
    """
    安全检查工具：评估 API 操作的安全级别，识别高风险操作。
    在调用 CommonAPICaller 之前使用此工具检查 API 安全性。
    """
    try:
        from ..security import get_security_controller, SecurityLevel

        config = get_config()
        security_controller = get_security_controller()

        # 初始化安全控制器配置
        if config.security:
            security_controller.set_enabled(config.security.enabled)
            if config.security.whitelist:
                security_controller.add_to_whitelist(config.security.whitelist)
            if config.security.blacklist:
                security_controller.add_to_blacklist(config.security.blacklist)

        # 评估 API 安全性
        security_level, reason = security_controller.evaluate_api_security(
            service=service,
            method=method,
            path=path,
            operation_id=operation_id,
            config_security=config.security
        )

        # 检查是否被允许
        allowed, allow_reason, _ = security_controller.is_api_allowed(
            service=service,
            method=method,
            path=path,
            operation_id=operation_id,
            require_confirmation=False
        )

        # 构建结果
        result = {
            "api_signature": f"{method.upper()} {path}",
            "service": service,
            "security_level": security_level.value,
            "evaluation_reason": reason,
            "is_allowed": allowed,
            "allow_reason": allow_reason,
        }

        # 添加安全级别说明
        level_descriptions = {
            SecurityLevel.SAFE.value: "✅ 安全操作 - 可以直接执行",
            SecurityLevel.MODERATE.value: "⚠️ 中等风险 - 建议谨慎执行",
            SecurityLevel.HIGH_RISK.value: "🚨 高风险操作 - 需要明确确认",
            SecurityLevel.FORBIDDEN.value: "🚫 禁止操作 - 不允许执行"
        }

        result["level_description"] = level_descriptions.get(
            security_level.value,
            "❓ 未知风险级别"
        )

        # 添加建议
        if security_level == SecurityLevel.SAFE:
            result["suggestion"] = "可以安全地使用 CommonAPICaller 执行此操作"
        elif security_level == SecurityLevel.MODERATE:
            result["suggestion"] = "可以使用 CommonAPICaller 执行，但请确认操作正确"
        elif security_level == SecurityLevel.HIGH_RISK:
            result["suggestion"] = "高风险操作！如确需执行，请使用 CommonAPICaller 并设置 force_execute=True"
        elif security_level == SecurityLevel.FORBIDDEN:
            result["suggestion"] = "此操作被安全策略禁止，无法执行"

        # 添加相关的安全提示
        if 'delete' in f"{method} {path}".lower():
            result["warning"] = "⚠️ 删除操作不可逆，请确保您真的需要删除此资源"
        elif 'restart' in f"{method} {path}".lower() or 'reboot' in f"{method} {path}".lower():
            result["warning"] = "⚠️ 重启操作会中断服务，请确保在合适的时间执行"
        elif 'stop' in f"{method} {path}".lower():
            result["warning"] = "⚠️ 停止操作会使服务不可用，请谨慎执行"

        logger.info(f"Security check completed for {method} {path}: {security_level.value}")
        return result

    except Exception as e:
        logger.error(f"Failed to perform security check: {e}")
        return {
            "error": f"安全检查失败: {str(e)}",
            "suggestion": "请检查输入参数是否正确"
        }


@tools.append
def ListAPIs(
    service: str = Field(description='InCloud service name (e.g., icompute, istorage)')
) -> List[Dict[str, Any]]:
    """
    Use PromptUnderstanding tool first to understand the user's query. 
    Get the corresponding API list information through the service name to prepare for the subsequent selection of the appropriate API to call.
    """
    try:
        config = get_config()
        swagger_client = SwaggerClient(config)
        
        apis = swagger_client.get_service_apis(service)
        
        # Format API list for better readability
        formatted_apis = []
        for api in apis:
            formatted_api = {
                'method': api['method'],
                'path': api['path'],
                'summary': api.get('summary', ''),
                'description': api.get('description', ''),
                'operationId': api.get('operationId', ''),
                'tags': api.get('tags', [])
            }
            formatted_apis.append(formatted_api)
        
        logger.info(f"Listed {len(formatted_apis)} APIs for service {service}")
        return formatted_apis
        
    except Exception as e:
        logger.error(f"Failed to list APIs for service {service}: {e}")
        return []


@tools.append
def GetAPIInfo(
    service: str = Field(description='InCloud service name'),
    method: str = Field(description='HTTP method (GET, POST, etc.)'),
    path: str = Field(description='API path')
) -> Dict[str, Any]:
    """
    Use PromptUnderstanding tool first to understand the user's query. 
    After specifying the service name, method, and API path, get the detailed API information including parameters.
    """
    try:
        config = get_config()
        swagger_client = SwaggerClient(config)
        
        api_details = swagger_client.get_api_details(service, method, path)
        
        if not api_details:
            return {"error": f"API not found: {method} {path} in service {service}"}
        
        # Extract and format parameter information
        parameters = swagger_client.extract_parameters(api_details)
        
        formatted_info = {
            'method': api_details['method'],
            'path': api_details['path'],
            'summary': api_details.get('summary', ''),
            'description': api_details.get('description', ''),
            'parameters': parameters,
            'responses': api_details.get('responses', {}),
            'tags': api_details.get('tags', [])
        }
        
        logger.info(f"Retrieved API info for {method} {path} in service {service}")
        return formatted_info
        
    except Exception as e:
        logger.error(f"Failed to get API info for {method} {path} in service {service}: {e}")
        return {"error": str(e)}


@tools.append
def CommonAPICaller(
    service: str = Field(description='InCloud service name'),
    method: str = Field(description='HTTP method'),
    path: str = Field(description='API path'),
    parameters: Dict[str, Any] = Field(description='API parameters', default_factory=dict),
    force_execute: bool = Field(default=False, description='Force execute high-risk operations (use with caution)')
) -> Any:
    """
    Use PromptUnderstanding tool first to understand the user's query.
    Perform the actual API call by specifying the Service, Method, Path, and Parameters.

    Security Note: High-risk operations (delete, restart, etc.) require force_execute=True.
    Use SecurityChecker tool first to evaluate API safety.
    """
    try:
        logger.info(f"CommonAPICaller called: {method} {path} in service {service}")
        logger.info(f"Input parameters: {parameters}")
        logger.info(f"Force execute: {force_execute}")

        # 直接检查是否为高风险方法（DELETE, PUT, PATCH）
        forbidden_methods = ['DELETE', 'PUT', 'PATCH']
        if method.upper() in forbidden_methods:
            method_descriptions = {
                'DELETE': '删除操作',
                'PUT': '修改操作',
                'PATCH': '更新操作'
            }

            operation_type = method_descriptions.get(method.upper(), '操作')

            error_msg = f"""
🚫 {operation_type}已被完全禁止

为了防止误操作导致资源损坏或服务中断，本系统不允许以下操作：
- ❌ DELETE：删除资源
- ❌ PUT：修改资源配置
- ❌ PATCH：更新资源属性

💡 建议替代方案：
1. 查询操作：GET /v1/resources 或 GET /v1/resources/{{id}}
2. 创建新资源：POST /v1/resources
3. 控制操作：POST /v1/resources/{{id}}/start|stop|restart
4. 联系系统管理员进行修改或删除操作

📋 如需了解更多信息，请使用 ResourceOperationBlocker 工具。
"""
            logger.warning(f"{method.upper()} operation blocked: {method} {path}")
            return {
                "error": error_msg,
                "blocked_operation": f"{method} {path}",
                "blocked_method": method.upper(),
                "reason": f"{method.upper()} operations are completely forbidden by security policy",
                "suggestion": "Use ResourceOperationBlocker tool for more information and alternatives"
            }

        config = get_config()

        # 安全检查
        from ..security import get_security_controller
        security_controller = get_security_controller()

        # 初始化安全控制器配置
        if config.security:
            security_controller.set_enabled(config.security.enabled)
            # 支持新的配置格式和旧的配置格式
            legacy_whitelist = getattr(config.security, 'whitelist', [])
            legacy_blacklist = getattr(config.security, 'blacklist', [])
            if legacy_whitelist:
                security_controller.add_to_whitelist(legacy_whitelist)
            if legacy_blacklist:
                security_controller.add_to_blacklist(legacy_blacklist)

        # 检查 API 是否被允许
        allowed, reason, security_level = security_controller.is_api_allowed(
            service=service,
            method=method,
            path=path,
            require_confirmation=force_execute,
            config_security=config.security
        )

        if not allowed:
            error_msg = f"🚫 API call blocked by security policy: {reason}"
            logger.warning(error_msg)
            return {
                "error": error_msg,
                "security_level": security_level.value,
                "suggestion": "Use SecurityChecker tool to evaluate this API, or set force_execute=True if you're certain about the operation"
            }

        # 如果是高风险操作但没有强制执行标志，给出警告
        if security_level.value == "high_risk" and not force_execute:
            warning_msg = f"⚠️ High-risk operation detected: {reason}. Use force_execute=True to proceed."
            logger.warning(warning_msg)
            return {
                "error": warning_msg,
                "security_level": security_level.value,
                "api_signature": f"{method} {path}",
                "suggestion": "This operation could be dangerous. If you're sure, call again with force_execute=True"
            }

        # 记录安全信息
        logger.info(f"Security check passed: {reason} (level: {security_level.value})")

        api_executor = APIExecutor(config)

        result = api_executor.execute_api(
            service_name=service,
            method=method,
            path=path,
            parameters=parameters
        )

        logger.info(f"Successfully executed API: {method} {path} in service {service}")
        logger.info(f"API result: {result}")
        return result

    except Exception as e:
        logger.error(f"Failed to execute API {method} {path} in service {service}: {e}")
        logger.error(f"Exception type: {type(e).__name__}")
        logger.error(f"Exception details: {str(e)}")
        return {"error": str(e)}


@tools.append
def ListServices() -> List[Dict[str, str]]:
    """
    Get list of available InCloud services from Swagger resources.
    """
    try:
        config = get_config()
        swagger_client = SwaggerClient(config)
        
        # Get services from Swagger resources
        resources = swagger_client.get_swagger_resources()
        services = []
        
        for resource in resources:
            service_info = {
                'name': resource.get('name', ''),
                'url': resource.get('url', ''),
                'version': resource.get('version', ''),
                'description': f"InCloud {resource.get('name', '').title()} Service"
            }
            services.append(service_info)
        
        # Also include configured services
        configured_services = config.get_enabled_services()
        for service_name, _ in configured_services.items():
            if not any(s['name'] == service_name for s in services):
                service_info = {
                    'name': service_name,
                    'url': '',
                    'version': '',
                    'description': f"InCloud {service_name.title()} Service (Configured)"
                }
                services.append(service_info)
        
        logger.info(f"Listed {len(services)} available services")
        return services
        
    except Exception as e:
        logger.error(f"Failed to list services: {e}")
        return []
